package com.openharmony.filepicker.slice;

import cn.bingoogolapple.refreshlayout.BgaStickinessRefreshViewHolder;
import cn.bingoogolapple.refreshlayout.BgarefreshLayout;
import com.openharmony.filepicker.FilePickerAbility;
import com.openharmony.filepicker.ResourceTable;
import com.openharmony.filepicker.adapter.BaseAdapter;
import com.openharmony.filepicker.adapter.FileListAdapter;
import com.openharmony.filepicker.adapter.FileNavAdapter;
import com.openharmony.filepicker.adapter.RecyclerViewListener;
import com.openharmony.filepicker.bean.BeanSubscriber;
import com.openharmony.filepicker.bean.FileBean;
import com.openharmony.filepicker.bean.FileItemBeanImpl;
import com.openharmony.filepicker.bean.FileNavBeanImpl;
import com.openharmony.filepicker.config.FileItemOnClickListener;
import com.openharmony.filepicker.config.FilePickerConfig;
import com.openharmony.filepicker.config.FilePickerManager;
import com.openharmony.filepicker.utils.FileUtils;
import com.openharmony.filepicker.utils.ToastUtil;
import com.openharmony.filepicker.widget.RecyclerViewFilePicker;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.utils.Color;
import ohos.agp.window.service.WindowManager;
import ohos.event.commonevent.CommonEventData;
import ohos.event.commonevent.CommonEventManager;
import ohos.event.commonevent.CommonEventSubscribeInfo;
import ohos.event.commonevent.CommonEventSubscriber;
import ohos.event.commonevent.MatchingSkills;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.rpc.RemoteException;

public class FilePickerAbilitySlice extends AbilitySlice implements BeanSubscriber,
        Component.ClickedListener,
        RecyclerViewListener.OnItemClickListener, BgarefreshLayout.BgarefreshLayoutDelegate {

    static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");

    private final long KEEP_ALIVE_TIME = 10L;

    private ComponentContainer listRootView;
    private RecyclerViewFilePicker rvList;

    private ListContainer rvNav = null;

    private Text tvToobarTitle;
    private Button btnConfirm;
    private Button btnSelectedAll;
    private Image btnGoBack;
    /**
     * 文件列表适配器
     */
    private FileListAdapter listAdapter;
    private EventHandler mainHandler = new EventHandler(EventRunner.getMainEventRunner());

    private BlockingQueue<Runnable> loadingFileWorkerQueue = new LinkedBlockingDeque<>();
    private ThreadPoolExecutor loadingThreadPool;

    /**
     * 导航栏数据集
     */
    private ArrayList<FileNavBeanImpl> navDataSource = new ArrayList<>();

    private FilePickerConfig pickerConfig;

    /**
     * 导航栏列表适配器
     */
    private FileNavAdapter navAdapter;

    /**
     * 文件夹为空时展示的空视图
     */
    private int selectedCount = 0;
    private int maxSelectable = 0;

    private RecyclerViewListener fileListListener;
    private RecyclerViewListener navListener;

    private HashMap<String, Integer> currPosMap = new HashMap<>(4);
    private HashMap<String, Integer> currOffsetMap = new HashMap<>(4);

    private Runnable loadFileRunnable = new Runnable() {
        @Override
        public void run() {

            File rootFile;

            rootFile = getContext().getExternalFilesDir(null);

            HiLog.error(LABEL, "--- start get root file path : " + rootFile.getAbsolutePath());

            if (navDataSource.isEmpty() && pickerConfig.isSkipDir()) {
//                rootFile = FileUtils.getRootFile(getContext()).getParentFile();
                rootFile = rootFile.getParentFile();
            } else if (navDataSource.isEmpty() && !pickerConfig.isSkipDir()) {
                // 如果是文件夹作为可选项时，需要让根目录也作为 item 被点击，故而取根目录上级作为 rootFiles
                rootFile = rootFile.getParentFile();
            } else {
                rootFile = new File(navDataSource.get(navDataSource.size() - 1).getFilePath());
            }

            HiLog.error(LABEL, "--- start run get root file " + getContext().getExternalFilesDir(null));

            ArrayList<FileItemBeanImpl> listData = FileUtils
                    .produceListDataSource(getContext(),
                            rootFile,
                            FilePickerAbilitySlice.this::updateItemUI);

            // 导航栏数据集
            String nextPath = "";
            if (navDataSource.isEmpty()) {
                nextPath = rootFile.getPath();
            } else {
                nextPath = navDataSource.get(navDataSource.size() - 1).getFilePath();
            }
            FileUtils.produceNavDataSource(
                    navDataSource,
                    nextPath,
                    getContext()
            );

            mainHandler.postTask(new Runnable() {
                @Override
                public void run() {
                    initRv(listData, navDataSource);
                }
            });
        }
    };

    private BgarefreshLayout bgaRefreshLayout;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_file_picker);

        loadingThreadPool = new ThreadPoolExecutor(
                1,
                1,
                KEEP_ALIVE_TIME,
                TimeUnit.MINUTES,
                loadingFileWorkerQueue
        );

        initView();

        loadList();
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    private void initView() {

        WindowManager.getInstance()
                .getTopWindow()
                .get()
                .setStatusBarColor(Color.getIntColor("#333333"));

        pickerConfig = FilePickerManager.INSTANCE().getConfig();
        maxSelectable = pickerConfig.getMaxSelectable();

        btnGoBack = (Image) findComponentById(ResourceTable.Id_btn_go_back_file_picker);
        btnGoBack.setClickedListener(this);
        btnSelectedAll = (Button) findComponentById(ResourceTable.Id_btn_selected_all_file_picker);
        if (pickerConfig.isSingleChoice()) {
            btnSelectedAll.setVisibility(Component.HIDE);
        }
        btnSelectedAll.setClickedListener(this);
        btnSelectedAll.setText(pickerConfig.getSelectAllText());

        btnConfirm = (Button) findComponentById(ResourceTable.Id_btn_confirm_file_picker);
        btnConfirm.setClickedListener(this);
        btnConfirm.setText(pickerConfig.getConfirmText());

        tvToobarTitle = (Text) findComponentById(ResourceTable.Id_tv_toolbar_title_file_picker);
        if (pickerConfig.isSingleChoice()) {
            tvToobarTitle.setVisibility(Component.INVISIBLE);
        } else {
            tvToobarTitle.setVisibility(Component.VISIBLE);
        }

        initRefresh();

        navAdapter = new FileNavAdapter(this);
        rvNav = (ListContainer) findComponentById(ResourceTable.Id_rv_nav_file_picker);
        rvNav.setItemProvider(navAdapter);

        listRootView =
                (ComponentContainer) findComponentById(ResourceTable.Id_file_picker_list_root);

        listAdapter = new FileListAdapter(getContext());
        rvList = (RecyclerViewFilePicker) findComponentById(ResourceTable.Id_rv_list_file_picker);
        rvList.setItemProvider(listAdapter);

        if (!rvList.hasEmptyView()) {
            Component emptyView = LayoutScatter
                    .getInstance(getContext())
                    .parse(ResourceTable.Layout_empty_file_list_file_picker,
                            null,
                            false);
            listRootView.addComponent(emptyView);
            rvList.setEmptyView(emptyView);
        }

        fileListListener = getListener(rvList);
        navListener = getListener(rvNav);
    }

    /**
     * 初始化刷新控件
     */
    private void initRefresh() {
        bgaRefreshLayout = (BgarefreshLayout) findComponentById(ResourceTable.Id_bgaRefreshLayout);
        bgaRefreshLayout.setDelegate(this);
        BgaStickinessRefreshViewHolder stickinessRefreshViewHolder =
                new BgaStickinessRefreshViewHolder(this, false);
        bgaRefreshLayout.setRefreshViewHolder(stickinessRefreshViewHolder);
        bgaRefreshLayout.setIsShowLoadingMoreView(false);
        bgaRefreshLayout.setPullDownRefreshEnable(true);
        stickinessRefreshViewHolder.setPullDownRefreshText("");
        stickinessRefreshViewHolder.setLoadingMoreText("");
        stickinessRefreshViewHolder.setUltimateColor(ResourceTable.Color_util_color);
        stickinessRefreshViewHolder.setLoaderTextColor(ResourceTable.Color_text_color);
        stickinessRefreshViewHolder.setPullUpDilogueVisible(false);
        stickinessRefreshViewHolder.setLoaderTextSize(50);
        stickinessRefreshViewHolder.setProgressSize(90);
    }

    private void loadList() {
        loadingThreadPool.submit(loadFileRunnable);
    }

    private void initRv(
            ArrayList<FileItemBeanImpl> listData,
            ArrayList<FileNavBeanImpl> navDataList
    ) {

        switchButton(true);
        // 导航栏适配器
        navAdapter.setNewData(navDataList);

        // 列表适配器
        listAdapter.setSingleChoice(pickerConfig.isSingleChoice());
        listAdapter.setNewData(listData);

    }

    private RecyclerViewListener getListener(ListContainer recyclerView) {
        if (recyclerView == null) {
            return null;
        }
        return new RecyclerViewListener(getAbility(), recyclerView, this);
    }

    @Override
    public void updateItemUI(boolean isCheck) {
        if (isCheck) {
            selectedCount++;
        } else {
            selectedCount--;
        }

        if (pickerConfig.isSingleChoice()) {
            return;
        }

        //取消选中，并且选中数为0
        if (selectedCount == 0) {
            if (btnSelectedAll != null) {
                btnSelectedAll.setText(pickerConfig.getSelectAllText());
            }
            if (tvToobarTitle != null) {
                tvToobarTitle.setText("");
            }
            return;
        }

        if (btnSelectedAll != null) {
            btnSelectedAll.setText(pickerConfig.getDeSelectAllText());
        }
        if (tvToobarTitle != null) {
            try {
                String title = getResourceManager().getElement(pickerConfig.getHadSelectedText()).getString(selectedCount);
                tvToobarTitle.setText(title);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotExistException e) {
                e.printStackTrace();
            } catch (WrongTypeException e) {
                e.printStackTrace();
            }

        }
    }

    private void switchButton(boolean isEnable) {
        if (btnConfirm != null) {
            btnConfirm.setEnabled(isEnable);
        }
        if (btnSelectedAll != null) {
            btnSelectedAll.setEnabled(isEnable);
        }
    }

    @Override
    public void onClick(Component component) {

        if (component.getId() == ResourceTable.Id_btn_selected_all_file_picker) { // 全选

            // 只要当前选中项数量大于 0，那么本按钮则为取消全选按钮
            if (selectedCount > 0) {
                listAdapter.disCheckAll();
            } else if (isCanSelect()) {
                // 当前选中数少于最大选中数，则即将执行选中
                listAdapter.checkAll(selectedCount);
            }
        } else if (component.getId() == ResourceTable.Id_btn_confirm_file_picker) { // 确认按钮

            if (listAdapter.getDataList() == null || listAdapter.getDataList().isEmpty()) {
                return;
            }
            ArrayList<String> list = new ArrayList<>();
            Intent intent = new Intent();

            for (FileItemBeanImpl data : listAdapter.getDataList()) {
                if (data.isChecked()) {
                    list.add(data.getFilePath());
                }
            }

            if (list.isEmpty()) {
                getAbility().setResult(FilePickerManager.RESULT_CANCELED, intent);
                terminateAbility();
            }

            FilePickerManager.INSTANCE().saveData(list);
            getAbility().setResult(FilePickerManager.RESULT_OK, intent);
            terminateAbility();

        } else if (component.getId() == ResourceTable.Id_btn_go_back_file_picker) {
            onBackPressed();

        }
    }

    private boolean isCanSelect() {
        return selectedCount < maxSelectable;
    }

    @Override
    protected void onBackPressed() {

        int count = 0;
        if (rvNav != null) {
            count = rvNav.getItemProvider().getCount();
        }
        if (count <= 1) {
            super.onBackPressed();
        } else {
            enterDirAndUpdateUI(navAdapter.getItem(navAdapter.getCount() - 2));
        }
    }

    /**
     * 从导航栏中调用本方法，需要传入 pos，以便生产新的 nav adapter
     */
    private void enterDirAndUpdateUI(FileBean fileBean) {

        resetViewState();
        // 获取文件夹文件
        File nextFiles = new File(fileBean.getFilePath());
        // 更新列表数据集
        listAdapter.setNewData(FileUtils.produceListDataSource(this, nextFiles, this));
        // 更新导航栏的数据集
        navDataSource = FileUtils.produceNavDataSource(
                new ArrayList<>(navAdapter.getDataList()),
                fileBean.getFilePath(),
                this
        );
        navAdapter.setNewData(navDataSource);
        int navCount = rvNav.getItemProvider().getCount();
//        if (navCount == 0) {
//            rvNav.scrollToCenter(0);
//        } else {
//            rvNav.scrollToCenter(-1);
//        }
        notifyDataChangedForList(fileBean);
    }

    private void notifyDataChangedForList(FileBean fileBean) {
        //TODO 暂未移植
    }

    private void resetViewState() {
        selectedCount = 1;
        updateItemUI(false);
    }

    /**
     * 保存当前文件夹被点击项，下次进入时将滑动到此
     */
    private void saveCurrPos(FileNavBeanImpl item, int position) {
        if (item != null) {
            currPosMap.put(item.getFilePath(), position);
            //TODO 未移植LinearLayoutManager
        }
    }

    /*--------------------------Item click listener begin------------------------------*/

    /**
     * 传递 item 点击事件给调用者
     */
    @Override
    public void onItemClick(BaseItemProvider adapter, Component view, int position) {
        System.out.println("===onItemClick===>" + position);
        if (adapter instanceof BaseAdapter) {
            FileBean item = ((BaseAdapter) adapter).getItem(position);
            if (item == null) {
                return;
            }
            File file = new File(item.getFilePath());
            if (!file.exists()) {
                return;
            }

            if (view.getId() == ResourceTable.Id_item_list_file_picker) {
                if (file.isDirectory()) {
                    if (rvNav.getItemProvider() instanceof FileNavAdapter) {
                        ArrayList<FileNavBeanImpl> dataList = ((FileNavAdapter) rvNav
                                .getItemProvider())
                                .getDataList();
                        FileNavBeanImpl last = dataList.get(dataList.size() - 1);
                        saveCurrPos(last, position);
                    }
                    // 如果是文件夹，则进入
                    enterDirAndUpdateUI(item);
                } else {
                    FileItemOnClickListener fileItemOnClickListener
                            = pickerConfig.getFileItemOnClickListener();
                    if (fileItemOnClickListener != null) {
                        fileItemOnClickListener
                                .onItemClick((FileListAdapter) adapter, view, position);
                    }
                }
            } else if (view.getId() == ResourceTable.Id_item_nav_file_picker) {
                if (file.isDirectory()) {
                    if (rvNav != null) {
                        ArrayList<FileNavBeanImpl> dataList = ((FileNavAdapter) rvNav
                                .getItemProvider())
                                .getDataList();
                        FileNavBeanImpl last = dataList.get(dataList.size() - 1);
                        saveCurrPos(last, position);
                    }
                    // 如果是文件夹，则进入
                    enterDirAndUpdateUI(item);
                }
            }

        }

    }

    @Override
    public void onItemLongClick(BaseItemProvider adapter, Component view, int position) {
        if (view.getId() != ResourceTable.Id_item_list_file_picker) {
            return;
        }
        FileItemBeanImpl item = ((FileListAdapter) adapter).getItem(position);
        if (item == null) {
            return;
        }
        File file = new File(item.getFilePath());
        boolean isSkipDir = pickerConfig.isSkipDir();
        // 如果是文件夹并且没有略过文件夹
        if (file.exists() && file.isDirectory() && isSkipDir) {
            return;
        }
        // same action like child click
        onItemChildClick(adapter, view, position);
        // notify listener
        FileItemOnClickListener fileItemOnClickListener = pickerConfig.getFileItemOnClickListener();
        if (fileItemOnClickListener != null) {
            fileItemOnClickListener.onItemLongClick((FileListAdapter) adapter, view, position);
        }
    }

    @Override
    public void onItemChildClick(BaseItemProvider adapter, Component view, int position) {
        System.out.println("===onItemChildClick===>" + position);
        if (pickerConfig.isSingleChoice()) {
            listAdapter.singleCheck(position);
        } else {
            FileItemBeanImpl item = ((FileListAdapter) adapter).getItem(position);
            listAdapter.multipleCheckOrNo(item, position, this::isCanSelect, new FileListAdapter.CheckFailedFunc() {
                @Override
                public void checkFailedFunc() {
                    try {
                        String msg = getResourceManager().getElement(pickerConfig.getMaxSelectCountTips()).getString(maxSelectable);
//                        new ToastDialog(FilePickerAbilitySlice.this).setText(msg).show();
                        ToastUtil.showToast(getContext(), msg);
                    } catch (IOException | NotExistException | WrongTypeException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }


    /*--------------------------Item click listener end------------------------------*/

    @Override
    public void onBgarefreshLayoutBeginRefreshing(BgarefreshLayout bgarefreshLayout) {

        HiLog.error(LABEL, "my load list on bga-----");

        loadList();
    }

    @Override
    public boolean onBgarefreshLayoutBeginLoadingMore(BgarefreshLayout bgarefreshLayout) {
        return false;
    }

}
